#include "../../../inc/mzhw.h"
#include "../../../inc/mzrtos.h"

mz_uint32_t mz_interrupt_thread_from;
mz_uint32_t mz_interrupt_thread_to;
mz_uint32_t mz_interrupt_flag;

#define YOU_USE_KEIL                           0

#if YOU_USE_KEIL
#include "ARMCM3.h"

void mz_hw_system_init(void){
    SysTick_Config( SystemCoreClock / MZ_TICK_TICK_PER_SECOND );
}

void SysTick_Handler(void){
    mz_uint32_t temp;
    temp = mz_hw_interrupt_disable();

    mz_tick_beat();
    mz_timer_check();

    mz_hw_interrupt_enable(temp);
}
#else
void mz_hw_system_init(void){

}

mz_uint32_t mz_hw_interrupt_disable(void){
    return 0;
}

void mz_hw_interrupt_enable(mz_uint32_t level){

}

void mz_hw_first_switch_to(mz_uint32_t target_sp){

}

void mz_hw_context_switch(mz_uint32_t from, mz_uint32_t to){

}
#endif

mz_uint8_t* mz_hw_stack_init(void* entry,
                             void* arg,
                             mz_uint8_t* stack_addr){
    mz_uint32_t i;
    mz_uint8_t* stk;
    struct stack_reg* stack_reg;

    stk = (mz_uint8_t*)stack_addr + sizeof(mz_uint32_t);

    stk = (mz_uint8_t*) MZ_ALIGN_DOWN((mz_uint32_t)stk, 8);

    stk -= sizeof(struct stack_reg);

    stack_reg = (struct stack_reg*)stk;

    for(i = 0; i < sizeof(struct stack_reg) / sizeof(mz_uint32_t); i++){
        ((mz_uint32_t*)stack_reg)[i] = 0xdeadbeaf;
    }

    stack_reg->exception_stack_reg.r0 = (mz_uint32_t)arg;
    stack_reg->exception_stack_reg.r1 = 0;
    stack_reg->exception_stack_reg.r2 = 0;
    stack_reg->exception_stack_reg.r3 = 0;
    stack_reg->exception_stack_reg.r12 = 0;

    stack_reg->exception_stack_reg.lr = 0;
    stack_reg->exception_stack_reg.pc = (mz_uint32_t)entry;
    stack_reg->exception_stack_reg.psr = 0x01000000L;

    return stk;
}